package com.lagou.server;

import lombok.Data;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Data
public class ResourcesLoad {
    public static Engine engine=new Engine();
    public static Map<String,String> DEMO_XML =new HashMap();
   // public static Map<String,String> DEMO_CLASS =new HashMap();
   public static Map<String,List<String>> DEMO_CLASS =new HashMap();
    private static Map<String,String> DEMO_HTML =new HashMap();
    public static Integer port;
    public static   Map<String,HttpServlet> servletMap=new HashMap<>();

    public static void loadServerXml() throws DocumentException {

        //1 加载解析 server.xml文件
        InputStream resourceAsStream = ResourcesLoad.class.getClassLoader().getResourceAsStream("conf/server.xml");

        SAXReader saxReader = new SAXReader();
        Document read = saxReader.read(resourceAsStream);
        //获取跟路径
        Element rootElement = read.getRootElement();

        Document document = rootElement.getDocument();

        //2 获取端口
        Element node = (Element) document.selectSingleNode("//Connector");
        port =Integer.valueOf(node.attributeValue("port"));
        //3 获取host
        Element element = (Element) document.selectSingleNode("//Host");
        //虚拟主机
        String localhost = element.attributeValue("name");
        //虚拟主机
        Host host = new Host();
        host.setHostName(localhost);
        List<Host>list = new ArrayList<>();
        list.add(host);
        engine.setHosts(list);

        //部署的地址路径
        String appBase = element.attributeValue("appBase");
        //4 根据这个路径去解析里面的项目 映射端口和虚拟主机，项目，以及url->servlet
        parseAppBase(appBase);
    }

    /**
     * 解析server.xml文件appBase
     * @param appBase
     */
    private static void parseAppBase(String appBase) {
        File file=new File(appBase);
        File[] files = file.listFiles();
        List<BaseContext> contextList = engine.getHosts().get(0).getContextList();
        for (File file1 : files) {
            List<String> classList=new ArrayList<>();
            String name = file1.getName();
            contextList.add(new BaseContext(name));
            doFile(file1.getPath(), name,classList);
        }
    }

    /**
     * 循环查找对应资源保存在map中 key为项目名字 value为资源路径
     * @param path
     * @param name
     */
    private static void doFile(String path, String name,List<String> classList) {
        File pathList = new File(path);
        File[] list1 = pathList.listFiles();
        if (list1 == null) {
            return;
        }
        //循环处理每个项目下web.xml
        for (File s : list1) {
            File file1 = new File(s.getPath());
            if (file1.isDirectory()) {
                doFile(file1.getPath(), name,classList);
            } else {
                if (s.getName().equals("web.xml")) {
                    //保存当前项目下的web.xml
                    DEMO_XML.put(name, s.getPath());
                }
                //保存字节码路径  这里目前只有一个class文件，其他业务class忽略...
                if (s.getName().endsWith(".class")) {
                    String classPath = s.getPath();
                    classList.add(classPath);
                }
            }
            }
        DEMO_CLASS.put(name, classList);
    }
    /**
     * 读取解析web.xml
     */
    public static void doWebXml() {
        for (Map.Entry<String, String> stringStringEntry : DEMO_XML.entrySet()) {

            String contextName = stringStringEntry.getKey();
            String xmlPath = stringStringEntry.getValue();

            try {
                loadServlet(contextName, xmlPath);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

        }

    }

    /**
     * 解析web.xml对应的servlet标签
     * @param contextName
     * @param xmlPath
     */
    private static void loadServlet(String contextName, String xmlPath) throws FileNotFoundException {
        //存储url  以及 配置servlet 以及请求url
        List<ContextWrapper> wrappersList = null;
        //获取上下文
        List<BaseContext> contextList = engine.getHosts().get(0).getContextList();
        for (BaseContext context1 : contextList) {
            if (contextName.equals(context1.getBaseName())) {
                wrappersList = context1.getWrappersList();
            }
        }

        //这里读取磁盘位置绝对路径的web.xml
        InputStream resourceAsStream = new FileInputStream(xmlPath);
        try {
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();

            List<Element> selectNodes = rootElement.selectNodes("//servlet");
            for (int i = 0; i < selectNodes.size(); i++) {
                Element element = selectNodes.get(i);
                // <servlet-name>server</servlet-name>
                Element servletnameElement = (Element) element.selectSingleNode("servlet-name");
                String servletName = servletnameElement.getStringValue();
                Element servletclassElement = (Element) element.selectSingleNode("servlet-class");
                String servletClass = servletclassElement.getStringValue();

                // 根据servlet-name的值找到url-pattern
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                // /server
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
                //servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClass).newInstance());

                ContextWrapper wrapper = new ContextWrapper();
                wrapper.setServletClass(servletClass);
                wrapper.setUrl(urlPattern);
                wrappersList.add(wrapper);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
    /**
     * 类加载实例化
     */
    public static void doNewInstance() {
        //获取上下文集合
        List<BaseContext> contextList1 = engine.getHosts().get(0).getContextList();
        //所有的上下文
        List<String> contextList = contextList1.stream().map(BaseContext::getBaseName).collect(Collectors.toList());
        //类加载实例化
        for (Map.Entry<String, List<String>> stringStringEntry : DEMO_CLASS.entrySet()) {
            String webDemoName = stringStringEntry.getKey();
            List<String> stringList = stringStringEntry.getValue();
            for (String s : stringList) {
              //  s=s.replaceAll("\\\\",".");
                //加载class 然后实例化
                MyClassLoader myClazz = new MyClassLoader();
                try {
                    Class<?> clazz = myClazz.findClass(s);
                    //根据url查找项目对应的servlet
                    if (contextList.contains(webDemoName)) {
                        for (BaseContext baseContext : contextList1) {
                            if(baseContext.getBaseName().equals(webDemoName)){
                                List<ContextWrapper> wrappersList = baseContext.getWrappersList();
                                //判断当前类是否在web.xml配置的servlet class里面
                                for (ContextWrapper contextWrapper : wrappersList) {
                                    if (s.replaceAll("/", ".").contains(contextWrapper.getServletClass())) {
                                        //保存实例对象
                                        try {
                                            contextWrapper.setObject(clazz.newInstance());
                                        } catch (InstantiationException e) {
                                            e.printStackTrace();
                                        } catch (IllegalAccessException e) {
                                            e.printStackTrace();
                                        }
                                    }
                                }
                            }
                        }
               /*     contextList1.stream().forEach(x -> {
                        if (x.getBaseName().equals(webDemoName)) {
                            List<ContextWrapper> wrappersList = x.getWrappersList();
                            //判断当前类是否在web.xml配置的servlet class里面
                            wrappersList.stream().forEach(x2 -> {
                                if (classPath.replaceAll("/", ".").equals(x2.getServletClass())) {
                                    //保存实例对象
                                    try {
                                        x2.setObject(clazz.newInstance());
                                    } catch (InstantiationException e) {
                                        e.printStackTrace();
                                    } catch (IllegalAccessException e) {
                                        e.printStackTrace();
                                    }
                                }
                            });

                        }
                    });*/
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    //加载web.xml
    public static  void loadServletXml() {
        InputStream resourceAsStream = ResourcesLoad.class.getClassLoader().getResourceAsStream("web.xml");
        SAXReader saxReader=new SAXReader();
        Document document = null;
        try {
            document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();
            List<Element> selectNodes = rootElement.selectNodes("//servlet");
            for (int i = 0; i < selectNodes.size(); i++) {
                Element element = selectNodes.get(i);
                Element servletElement = (Element) element.selectSingleNode("servlet-name");
                String servletName=servletElement.getStringValue();
                Element servletClassElement = (Element)element.selectSingleNode("servlet-class");
                String servletClass = servletClassElement.getStringValue();
                //根据servlet-Name找到url-pattern
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
                try {
                    servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClass).newInstance());
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}
